Apple II
Technical Notes
_____________________________________________________________________________
                                                  Developer Technical Support

Apple IIGS
#51:    Reserving Memory for the Toolbox

Written by:    Eric Soldan                                       January 1989

This Technical Note discusses handling nearly-out-of-memory situations when 
working with the IIGS tools.
_____________________________________________________________________________


Introduction

Running out of memory is a concern for most every application.  Working with 
the Toolbox makes monitoring this situation a little more difficult since your 
application is not the only one allocating memory.

Just waiting for an out-of-memory error is not necessarily adequate memory 
management.  If you execute a NewHandle call successfully, there could be any 
amount of memory left, from one byte to nearly all of it.  If there is not 
much memory left, there might not be enough for the Toolbox.  A better scheme 
of memory management would be to determine when the tools will need more 
memory than is available.  You can treat this situation as "out-of-memory" as 
well.

The Memory Manager calls to determine how much memory is available are 
MaxBlock, FreeMem, and RealFreeMem.  However, none of these calls can give you 
the complete picture.  FreeMem does not count purgeable handles.  RealFreeMem 
does count purgeable handles, but memory may be very fragmented.  MaxBlock can 
only tell you if you have enough RAM in a single block to complete a new 
handle request, but it does not provide a good indication of when you do not 
have enough, since memory may be fragmented.

Another way of determining if you have enough memory is with the NewHandle 
call.  If you know that you are going to do a sequence of operations that will 
not exceed N bytes of RAM, you can try a NewHandle call for that number of 
bytes.  If it works, dispose the temporary handle and go for it.  Of course, 
this may leave no memory available for the Toolbox, but you could fix this by 
trying a NewHandle of size N+ToolboxNeeds.  The problem with this method is 
that NewHandle is not the fastest Memory Manager call, and executing it 
repeatedly can seriously degrade the performance of your application.


A Suggested Method

Another method of checking for a nearly-out-of-memory condition is to have 
your own purgeable handle just for this task.  You can use the purgeable 
handle as a check for a nearly-out-of-memory situation.  If the handle has not 
been purged, then you have plenty of memory for the Toolbox, and in the worst 
case, the Toolbox will purge your handle if it needs the RAM.

The less often your purgeable handle gets purged, the better performance you 
will probably get in nearly-out-of-memory situations.  Therefore, the purge 
level of this handle should probably be 1.  (It might be better to have your 
handle purged before several other purgeable handles which are of greater use 
and could belong to you or others in the system.)  The check to see if a 
handle has been purged is very fast.  If it has been purged, you will have to 
see if it can be reallocated which is not a fast process, so the fewer times 
the handle is purged, the faster the check will be and the better your 
performance.  Unless you are in a nearly-out-of-memory situation, the handle 
will not be purged at all, and you will have virtually no overhead for this 
process.

This technique could be implemented as follows:

appStart              ;
;
;
;                     Somewhere at start, create a purgeable handle of size N,
;                     called "loMemHndl", purge level 1.
;
;
                      rts

******************
;            
;                     Here's an example of checking for nearly-out-of-memory:
;
                      jsr    preCheckLoMem
                      bcc    goForIt
                      bcs    HandleError            ;Handle errors appropriately.
goForIt               (_ToolboxCall[s])             ;Make as many as needed.
;
;                     Here you can make your toolbox calls.  Since you prechecked
;                     for nearly-out-of-memory conditions, you should have no memory
;                     errors at this point.
;
;                     You could also check after calls, as shown here:
;
                      (_ToolboxCall)
                      jsr    checkLoMem             ;Call this to see if low.
                      bcc    noError
                      bcs    HandleError            ;Take care of errors.

noError               jsr    lifeIsGood
                      .
                      .
                      .
                      rts

******************

******************

;
;                     Here are some sample routines to check for the nearly-out-of-
;                     memory condition.
;

checkLoMem            bcs    retErr
preCheckLoMem         lda    [loMemHndl]
                      ldy    #2
                      ora    [loMemHndl],y
                      beq    gotPurged
                      lda    #0
                      clc
                      rts
gotPurged             (Try reallocating it into loMemHndl, purge level 1.)
                      (If you can't, you will get a $0201 error.  You may wish to 
                      return the $201 error, or you may wish to change it into
                      your own error code.)
;
retErr                rts                        ;This is a single exit point
                                                 ;whether errors were present
                                                 ;or not.

You can determine the size of this purgeable handle, but, like determining 
what size stack is adequate for an application, there is no single "right" 
answer.  There are different considerations for size of the purgeable handle 
for each application, and these may change during the development process.  
Use your best judgement.


Conclusion

This Note is not meant to suggest that nearly-out-of-memory situations 
require detection in this way, and there are many applications which 
allocate enough RAM when they start (i.e., many paint programs) that if they 
get the requested memory, they will not encounter out-of-memory situations 
during that session.  There may also be other ways for a particular 
application to detect and handle nearly-out-of-memory situations, but this 
Note addresses this situation in a general way and offers only one solution 
for your consideration.


Further Reference:
_____________________________________________________________________________
o    Apple IIGS Toolbox Reference, Volumes 1 & 2

